package com.ntd.study.base.jvm;

/**
 * 垃圾回收
 * 1.垃圾回收主要是回收堆内存
 * 2.垃圾回收基于分代的思想
 * <p>
 * 堆内存分代
 * 新生代 Young：Eden 8/10、from 1/10、to 1/10 - 1/3 空间
 * 老年代 Old 2/3空间
 * |--对象分配
 * 1.优先分配在 Eden 区
 * 2.Eden 不够分配时，VM 发起一次 Minor GC，将Eden区和其中一块Survivor区内尚存活的对象放入另一块Survivor区域。
 * 3.如Minor GC 时survivor空间不够，对象提前进入老年代
 * 4.老年代空间不够进行Full GC
 * 5.大对象直接进入老年代 - 避免在Eden区和Survivor区之间来回复制，以及还有不少空闲内存就提前触发GC以获取足够的连续空间。
 * |--对象晋级
 * 1.VM为每个对象定义了一个对象年龄计数器
 * 2.经过一次Minor GC后仍然存活，年龄增加1
 * 3.增加到一定程度（-XX:MaxTenuringThreshold 默认15），晋升进入老年代
 * 4.提前晋升：如果Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半，年龄大于或等于改年龄的对象就可以直接进入老年代。
 * <p>
 * Minor GC过程 ->
 * 1.清除非存活对象
 * 2.Eden区和form区所有存活对象拷贝到to区 - 所有对象增加一岁
 * 3.form区和to区互换
 * <p>
 * 可达性分析算法 - 判断对象是否可被回收
 * |-- 通过GC Roots的对象作为起点，然后向下搜索，搜索走过的路径成为引用链/Reference Chain，当一个对象到GC Roots没有任何引用链相连时，即该对象不可达，也就说明此对象是不可用的。
 * GC Roots对象包括
 * 1.方法区：类静态属性引用的对象
 * 2.方法区：常量引用的对象
 * 3.虚拟机栈（本地变量表）中引用的对象
 * 4.本地方法栈JNI（Native方法）中引用的对象
 * <p>
 * 标记清除法
 * |-- 1.首先标记出来需要回收的对象
 * |-- 2.在标记完成后同意i清理掉所有被标记的对象
 * |-- 效率不高、产生大量不连续的内存碎片
 * 复制算法 - 适合新生代 - 不过新生代使用的方式做了优化
 * |-- 1.将可用内存分为大小相等的两块，每次只用其中一块
 * |-- 2.当内存用完将全部存活对象复制到另外一块上面，然后把使用过的内存空间一次清理掉
 * |-- 不会产生内存碎片、内存只有一半、对象存活率较高的时候要执行较多的复制操作，效率变低、如果不使用50%的对分策略，老年代需要考虑空间担保策略
 * 标记整理算法 - 适合老年代
 * |-- 1.标记出来需要回收的对象
 * |-- 2.标记完成后让所有存活的对象向一端移动
 * |-- 3.清理掉边界以外的内存
 * |-- 不会损失空间、没有内存碎片、适合大量存活对象的垃圾回收、效率不高
 * 分代收集 - jvm 实际使用的算法
 * |-- 1.不同的区域采用不同的算法
 * <p>
 * 吞吐量：运行用户代码时间/（运行用户代码时间+垃圾收集时间）
 * 垃圾收集时间：垃圾回收频率 * 单次垃圾回收时间
 * 垃圾回收器
 * 新生代
 * Serial、ParNew、Parallel Scavenge
 * |-- Serial：新生代，复制算法，单线程，回收时暂停程序、简单高效、适合内存不大的情况
 * |-- ParNew：新生代，复制算法，多线程 - 并行，搭配CMS垃圾回收器的首选
 * |-- Parallel Scavenge（吞吐量优先收集器）：新生代，复制算法，多线程 - 并行，更加关注吞吐量，jdk7，jdk8默认的新生代垃圾回收器，server级别多CPU机器的 默认GC方式。
 * 老年代
 * CMS、Serial Old MSC、Parallel Old
 * |-- Serial Old：老年代，标记整理算法，单线程，jdk7，jdk8默认的老年代垃圾回收器，client模式下虚拟机使用
 * |-- Parallel Old：老年代，标记整理算法，多线程 - 并行，为了配合Parallel Scavenge的面向吞吐量的特性而开发的对应组合，关注吞吐量
 * |-- CMS：老年代，标记清除算法，并行 - 并发，尽可能缩短用户线程停止时间，缺点：内存碎片、cpu资源、浮动垃圾问题、需要更大的堆空间，重视服务的响应速度、系统停顿时间、一般用于B/S系统，互联网后端目前cms是主流的垃圾回收器。
 * 综合 G1
 * |-- 跨新生代和老年代，标记整理+化整为零算法，并行 - 并发，jdk1.7正式引入，采用分区回收的思维，基本不牺牲吞吐量的前提下完成低停顿的内存回收，可预测停顿是最大的优势，面向服务端应用的垃圾回收器，目标为取代CMS
 * |-- 区域划分 -- 增加Humongous - 专门用来存储大对象
 * |-- 整个堆内存划分成碎片化 分为四种类型 - Eden、Survivor、Old、Humongous
 * <p>
 * JVM 客户端模式（Client）：默认的垃圾收集器 Serial GC
 * JVM 服务端模式（Server）：默认的垃圾收集器 Parallel GC
 * <p>
 * server 建议
 * ParNew + CMS + SerialOld（失败担保）
 * Parallel Scavenge + Parallel
 * <p>
 * minor GC：从年轻代空间回收内存
 * |-- 触发条件：当Eden区满时，进行 minor GC
 * Major GC：从老年代空间回收内存
 * Full GC：是对整个堆来说进行内存回收
 * |--触发条件：
 * |---- System.gc()
 * |---- 老年代空间不足
 * |---- 永生区空间不足
 * |---- 堆中分配很大的对象
 * |---- 统计得到的 minor GC晋升到旧生代的平均大小大于老年代的剩余空间
 */
public class DemoGarbage {
}
